#pragma once

//#include <srs_app_forward.hpp>
#include <srs_core.hpp>
#include <srs_app_st.hpp>
#include <srs_app_thread.hpp>

#include <string>

class ISrsProtocolReaderWriter;
class SrsSharedPtrMessage;
class SrsOnMetaDataPacket;
class SrsMessageQueue;
class SrsRtmpJitter;
class SrsRtmpClient;
class SrsRequest;
class SrsSource;
class SrsKbps;

/**
* forward the stream to other servers.
*/
// TODO: FIXME: refine the error log, comments it.
class SrsForwarder : public ISrsReusableThread2Handler {
private:
    // the ep to forward, server[:port].
    std::string _ep_forward;
    SrsRequest* _req;
    int stream_id;
private:
    st_netfd_t stfd;
    SrsReusableThread2* pthread;
private:
    SrsSource* source;
    ISrsProtocolReaderWriter* io;
    SrsKbps* kbps;
    SrsRtmpClient* client;
    SrsRtmpJitter* jitter;
    SrsMessageQueue* queue;
    /**
    * cache the sequence header for retry when slave is failed.
    */
    SrsSharedPtrMessage* sh_audio;
    SrsSharedPtrMessage* sh_video;
public:
    SrsForwarder(SrsSource* _source);
    virtual ~SrsForwarder();
public:
    virtual int initialize(SrsRequest* req, const std::string& ep_forward);
    virtual void set_queue_size(double queue_size);
public:
    virtual int on_publish();
    virtual void on_unpublish();
    /**
    * forward the audio packet.
    * @param shared_metadata, directly ptr, copy it if need to save it.
    */
    virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata);
    /**
    * forward the audio packet.
    * @param shared_audio, directly ptr, copy it if need to save it.
    */
    virtual int on_audio(SrsSharedPtrMessage* shared_audio);
    /**
    * forward the video packet.
    * @param shared_video, directly ptr, copy it if need to save it.
    */
    virtual int on_video(SrsSharedPtrMessage* shared_video);
    // interface ISrsReusableThread2Handler.
public:
    virtual int cycle();
private:
    virtual void close_underlayer_socket();
    virtual void discovery_ep(std::string& server, std::string& port, std::string& tc_url);
    virtual int connect_server(std::string& ep_server, std::string& ep_port);
    virtual int connect_app(const std::string& ep_server, const std::string& ep_port);
    virtual int forward();
};
